using System;
using System.Xml;
using DesignByContract;
using Outcoding.GraphGenerator.Entities;
using Outcoding.GraphGenerator.Util.Logging;

namespace Outcoding.GraphGenerator.Composition{
    public class GraphBuilder : BuilderBase{
        #region Attributes

        private string typeAttr = "type";

        #endregion

        private readonly string mNodeName = XmlTagNames.graph.ToString();

        private XmlNode mNode;

        private string mNodePath{
            get { return "./" + mNodeName; }
        }

        public override void SelectNode(XmlDocument document){
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Compose(){
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Compose(XmlNode node){
            mNode = node.SelectSingleNode(mNodePath);
            try{
                BuildObject(mNode);
            }
            catch (PreconditionException preExc){
                LogManager.Instance.LogWarning("Graph entity could not be created; process aborted.", preExc);
            }
        }

        public override void AppendToParent(object parent){
            Check.Require(parent is Shape, "Parent object not a valid argument");
            ((Shape) parent).Content = (Graph) mProduct;
        }

        private void BuildObject(XmlNode graphXmlNode){
            var graph = new Graph();
            try{
                graph.Type = ParseTypeAttribute(graphXmlNode);
            }
            catch (PreconditionException preExc){
                //log error
                graph = null;
                throw;
            }

            mProduct = graph;
        }

        private ChartType ParseTypeAttribute(XmlNode graphXmlNode){
            Check.Require(graphXmlNode.Attributes[typeAttr] != null, "typeAttr attribute not present");
            return ConvertTypeFromName(graphXmlNode.Attributes[typeAttr].Value);
        }

        private ChartType ConvertTypeFromName(string typeName){
            Check.Require(!string.IsNullOrEmpty(typeName), "Type name not defined");

            ChartType type = ChartType.xlUnknown;
            switch (typeName){
                case "xlLine":
                    type = ChartType.xlLine;
                    break;
                case "xlLineMarkers":
                    type = ChartType.xlLineMarkers;
                    break;
                case "xlColumnClustered":
                    type = ChartType.xlColumnClustered;
                    break;
                case "xlColumnStacked":
                    type = ChartType.xlColumnStacked;
                    break;
                case "xlColumnStacked100":
                    type = ChartType.xlColumnStacked100;
                    break;
                case "xl3DColumn":
                    type = ChartType.xl3DColumn;
                    break;
                case "xl3DColumnClustered":
                    type = ChartType.xl3DColumnClustered;
                    break;
                case "xl3DColumnStacked":
                    type = ChartType.xl3DColumnStacked;
                    break;
                case "xl3DColumnStacked100":
                    type = ChartType.xl3DColumnStacked100;
                    break;
                case "xlBarClustered":
                    type = ChartType.xlBarClustered;
                    break;
                case "xlBarStacked":
                    type = ChartType.xlBarStacked;
                    break;
                case "xlBarStacked100":
                    type = ChartType.xlBarStacked100;
                    break;
                case "xl3DBarClustered":
                    type = ChartType.xl3DBarClustered;
                    break;
                case "xl3DBarStacked":
                    type = ChartType.xl3DBarStacked;
                    break;
                case "xl3DBarStacked100":
                    type = ChartType.xl3DBarStacked100;
                    break;
                case "xlTableOnly":
                    type = ChartType.xlTableOnly;
                    break;
                default:
                    //unknown
                    break;
            }
            return type;
        }
    }
}